<%#
kind: snippet
name: puppet_setup
model: ProvisioningTemplate
snippet: true
description: |
  Bootstraps the Puppet agent and performs one run to create a certificate request.

  In more details it installs a Puppet agent, creates the necessary configuration files,
  enables the Puppet agent service and performs a single run with a specified tag.
  By default the tag `no_such_tag` is used to generate an empty run.
  An empty run can be used for the agent to detect it's missing a client certificate
  and ask for a new one from the host's Puppet CA.
-%>
<%
os_family = @host.operatingsystem.family
os_major  = @host.operatingsystem.major.to_i
os_name   = @host.operatingsystem.name

aio_enabled = host_param_true?('enable-puppetlabs-repo') || host_param_true?('enable-official-puppet8-repo') || host_param_true?('enable-puppet8') || host_param_true?('enable-official-puppet7-repo') || host_param_true?('enable-puppet7') || host_param_true?('enable-puppetlabs-puppet6-repo') || host_param_true?('enable-puppet6') || host_param_true?('enable-puppetlabs-puppet5-repo') || host_param_true?('enable-puppet5')
aio_openvox_enabled = host_param_true?('enable-openvox7') || host_param_true?('enable-openvox8')

if host_param('run-puppet-in-installer-tags')
  puppet_tags = host_param('run-puppet-in-installer-tags')
else
  puppet_tags = 'no_such_tag'
end

if os_family == 'Freebsd'
  freebsd_package = host_param_true?('enable-puppet6') ? 'puppet6' : 'puppet5'
  etc_path = '/usr/local/etc/puppet'
  bin_path = '/usr/local/bin'
elsif os_family == 'Windows'
  windows_package = "puppet-agent-#{@host.architecture}.msi"
  etc_path = 'C:\ProgramData\PuppetLabs\puppet\etc'
  bin_path = 'C:\Program Files\Puppet Labs\Puppet\bin'
elsif aio_enabled
  linux_package = 'puppet-agent'
  etc_path = '/etc/puppetlabs/puppet'
  bin_path = '/opt/puppetlabs/bin'
elsif aio_openvox_enabled
  linux_package = 'openvox-agent'
  etc_path = '/etc/puppetlabs/puppet'
  bin_path = '/opt/puppetlabs/bin'
else
  linux_package = os_family == 'Suse' ? 'rubygem-puppet' : 'puppet'
  etc_path = '/etc/puppet'
  bin_path = '/usr/bin'
end
-%>
<% if os_family == 'Debian' -%>
apt-get update
apt-get install -y <%= linux_package %>
<% elsif os_family == 'Freebsd' -%>
pkg install -y <%= freebsd_package %>
<% elsif os_family == 'Redhat' -%>
if [ -f /usr/bin/dnf ]; then
  dnf -y install <%= linux_package %>
else
  yum -t -y install <%= linux_package %>
fi
<% elsif os_family == 'Suse' -%>
<% if aio_enabled -%>
rpmkeys --import https://yum.puppet.com/RPM-GPG-KEY-puppet
<% elsif aio_openvox_enabled -%>
rpmkeys --import https://yum.voxpupuli.org/GPG-KEY-openvox.pub
<% end -%>
<% if @host.provision_method == 'image' -%>
/usr/bin/zypper -n --gpg-auto-import-keys install <%= linux_package %>
<% end -%>
<% elsif os_family == 'Windows' -%>
$puppet_agent_msi = "${env:TEMP}\<%= windows_package %>"
$puppet_install_args = @(
  '/qn',
  '/norestart',
  '/i',
  "${puppet_agent_msi}",
  <%- if host_puppet_ca_server.present? -%>
  "PUPPET_CA_SERVER=<%= host_puppet_ca_server %>",
  <%- end -%>
  "PUPPET_MASTER_SERVER=<%= host_puppet_server %>"
)

Write-Host "Installing ${puppet_agent_msi} with args ${puppet_install_args}"
Start-Process 'msiexec.exe' -ArgumentList $puppet_install_args -Wait -NoNewWindow
<% end -%>

<% if os_family == 'Windows' -%>
$puppet_conf = @("<%= snippet 'puppet.conf' %>".Replace("`n","`r`n"))
Out-File -FilePath <%= etc_path %>\puppet.conf -InputObject $puppet_conf
<% else -%>
cat > <%= etc_path %>/puppet.conf << EOF
<%= snippet 'puppet.conf' %>
EOF
<% end -%>

<% if @host.puppetca_token.present? -%>
<% if os_family == 'Windows' -%>
$csr_attributes = @("<%= snippet 'csr_attributes.yaml' %>".Replace("`n","`r`n"))
Out-File -FilePath <%= etc_path %>\csr_attributes.yaml -InputObject $csr_attributes
<% else -%>
cat > <%= etc_path %>/csr_attributes.yaml << EOF
<%= snippet 'csr_attributes.yaml' %>
EOF
<% end -%>
<% end -%>

<% if os_family == 'Redhat' -%>
<% if os_major > 6 -%>
puppet_unit=puppet
/usr/bin/systemctl list-unit-files | grep -q puppetagent && puppet_unit=puppetagent
/usr/bin/systemctl enable ${puppet_unit}
<% else -%>
/sbin/chkconfig --level 345 puppet on
<% end -%>
<% end -%>
<% if os_family == 'Freebsd' -%>
echo 'puppet_enable="YES"' >>/etc/rc.conf
<% end -%>
<% unless aio_enabled || aio_openvox_enabled -%>
<% if os_family == 'Debian' -%>
if [ -f "/etc/default/puppet" ]
then
/bin/sed -i 's/^START=no/START=yes/' /etc/default/puppet
fi
<%= bin_path %>/puppet agent --enable
<% elsif os_family == 'Suse' -%>
if [ -f "/etc/sysconfig/puppet" ]
then
/usr/bin/sed -ie s/^PUPPET_SERVER=.*/PUPPET_SERVER=<%= host_puppet_server %>/ /etc/sysconfig/puppet
fi
<% end -%>
<% end -%>
<%#
IMPORTANT NOTE: Setting "run-puppet-in-installer" is UNSUPPORTED!

The default mode of operation in Foreman is only to set up Puppet, but to not run it inside the installer environment.
Running Puppet inside the installer can cause various hard to diagnose errors, many of them resulting from the fact that
services are not started inside the installer.

If you are aware of the downsides, you can trigger a Puppet run inside the installer by setting the variable
run-puppet-in-installer to true.

Note, that this is an *unsupported mode of operation* and not supported by Foreman at all. You have been warned!
%>
<% if host_param_true?('run-puppet-in-installer') -%>
<% if (os_name == 'Ubuntu' && os_major >= 15) || (os_name == 'Debian' && os_major >= 8) -%>
# Puppet tries to detect the init system by checking the presence of the directory /run/systemd/system. That detection
# fails in a chroot environment like the one the installer provides. See Puppet tickets PA-136 and PUP-5577
#
# We work around that here until it gets fixed in Puppet (probably never for Puppet 3.x)
mkdir -p /run/systemd/system
<% end -%>
<% end -%>
# export a custom fact called 'is_installer' to allow detection of the installer environment in Puppet modules
<% if os_family == 'Windows' -%>
$env:FACTER_is_installer = $TRUE

# passing a non-existent tag like "no_such_tag" to the puppet agent only initializes the node
# You can select specific tag(s) with the "run-puppet-in-installer-tags" parameter
# or set a full puppet run by setting "run-puppet-in-installer" = true
$puppet_agent_args = @(
  "agent",
  "--config", "<%= etc_path %>\puppet.conf",
  "--onetime",
  <%= host_param_true?('run-puppet-in-installer') || @full_puppet_run ? '' : "\"--tags #{puppet_tags}\"," %>
  <%= host_puppet_server.blank? ? '' : "\"--server #{host_puppet_server}\"," %>
  "--no-daemonize"
)
Start-Process '<%= bin_path %>\puppet' -ArgumentList $puppet_agent_args -Wait -NoNewWindow
<% else -%>
export FACTER_is_installer=true
# passing a non-existent tag like "no_such_tag" to the puppet agent only initializes the node
# You can select specific tag(s) with the "run-puppet-in-installer-tags" parameter
# or set a full puppet run by setting "run-puppet-in-installer" = true
<% if host_param_true?('run-puppet-in-installer') || @full_puppet_run -%>
echo "Performing initial full puppet run"
<% else -%>
echo "Performing initial puppet run for --tags <%= puppet_tags %>"
<% end -%>
<%= bin_path %>/puppet agent --config <%= etc_path %>/puppet.conf --onetime <%= host_param_true?('run-puppet-in-installer') || @full_puppet_run ? '' : "--tags #{puppet_tags}" %> <%= host_puppet_server.blank? ? '' : "--server #{host_puppet_server}" %> --no-daemonize
<% if os_family == 'Suse' || (os_name == 'Debian' && os_major > 8) || (os_name == 'Ubuntu' && os_major >= 15) -%>
<% if os_family == 'Suse' -%>
<%= bin_path %>/puppet resource service puppet enable=true
<% else -%>
systemctl enable puppet
<% end -%>
<% end -%>
<% if @host.provision_method == 'image' -%>
<%= bin_path %>/puppet resource service puppet ensure=running
<% end -%>
<% end -%>
